﻿/*******************************************************************************
 * AAEngine
 * Copyright (c) 2010 Mike Jarosch
 *
 * Original source PushButton Engine:
 * Copyright (C) 2009 PushButton Labs, LLC
 * For more information see http://www.pushbuttonengine.com
 *
 * This file is licensed under the terms of the MIT license, which is included
 * in the "MIT License.txt" file at the root directory of this SDK.
 ******************************************************************************/

using System;
using System.Collections.Generic;
using Box2D.XNA;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using AAEngine.Rendering2D;

namespace AAEngine.Box2D
{
    public class DebugDrawer : DebugDraw
    {
        private RenderQueue _renderQueue;

        public RenderQueue RenderQueue 
        {
            set
            {
                _renderQueue = value;
            }
        }

        public override void DrawPolygon(ref FixedArray8<Vector2> vertices, int count, Color color)
        {
            List<Vertex2D> verts = new List<Vertex2D>();

            for (int i = 0; i < count - 1; i++)
            {
                verts.Add(new Vertex2D(vertices[i], color));
                verts.Add(new Vertex2D(vertices[i + 1], color));
            }

            verts.Add(new Vertex2D(vertices[count - 1], color));
            verts.Add(new Vertex2D(vertices[0], color));

            RenderInstance ri = new RenderInstance();
            ri.Type = RenderInstanceType.LineList;
            ri.Vertices = verts;
            _renderQueue.AddRenderInstance(ri);
        }

        public override void DrawSolidPolygon(ref FixedArray8<Vector2> vertices, int count, Color color)
        {
            DrawSolidPolygon(ref vertices, count, color, true);
        }

        private void DrawSolidPolygon(ref FixedArray8<Vector2> vertices, int count, Color color, bool outline)
        {
            if (count == 2)
            {
                DrawPolygon(ref vertices, count, color);
                return;
            }

            Color colorFill = color * (outline ? 0.5f : 1.0f);

            List<Vertex2D> verts = new List<Vertex2D>();

            for (int i = 1; i < count - 1; i++)
            {
                verts.Add(new Vertex2D(vertices[0], colorFill));
                verts.Add(new Vertex2D(vertices[i], colorFill));
                verts.Add(new Vertex2D(vertices[i + 1], colorFill));
            }

            RenderInstance ri = new RenderInstance();
            ri.Type = RenderInstanceType.TriangleList;
            ri.Vertices = verts;
            _renderQueue.AddRenderInstance(ri);

            if (outline)
            {
                DrawPolygon(ref vertices, count, color);
            }
        }

        public override void DrawCircle(Vector2 center, float radius, Color color)
        {
            int segments = 16;
            double increment = Math.PI * 2.0 / (double)segments;
            double theta = 0.0;

            List<Vertex2D> verts = new List<Vertex2D>();

            for (int i = 0; i < segments; i++)
            {
                Vector2 v1 = center + radius * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));
                Vector2 v2 = center + radius * new Vector2((float)Math.Cos(theta + increment), (float)Math.Sin(theta + increment));

                verts.Add(new Vertex2D(v1, color));
                verts.Add(new Vertex2D(v2, color));

                theta += increment;
            }

            RenderInstance ri = new RenderInstance();
            ri.Type = RenderInstanceType.LineList;
            ri.Vertices = verts;
            _renderQueue.AddRenderInstance(ri);
        }

        public override void DrawSolidCircle(Vector2 center, float radius, Vector2 axis, Color color)
        {
            int segments = 16;
            double increment = Math.PI * 2.0 / (double)segments;
            double theta = 0.0;

            Color colorFill = color * 0.5f;

            Vector2 v0 = center + radius * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));
            theta += increment;

            List<Vertex2D> verts = new List<Vertex2D>();

            for (int i = 1; i < segments - 1; i++)
            {
                Vector2 v1 = center + radius * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));
                Vector2 v2 = center + radius * new Vector2((float)Math.Cos(theta + increment), (float)Math.Sin(theta + increment));

                verts.Add(new Vertex2D(v0, colorFill));
                verts.Add(new Vertex2D(v1, colorFill));
                verts.Add(new Vertex2D(v2, colorFill));

                theta += increment;
            }

            RenderInstance ri = new RenderInstance();
            ri.Type = RenderInstanceType.TriangleList;
            ri.Vertices = verts;
            _renderQueue.AddRenderInstance(ri);

            DrawCircle(center, radius, color);

            DrawSegment(center, center + axis * radius, color);
        }

        public override void DrawSegment(Vector2 p1, Vector2 p2, Color color)
        {
            List<Vertex2D> verts = new List<Vertex2D>();

            verts.Add(new Vertex2D(p1, color));
            verts.Add(new Vertex2D(p2, color));

            RenderInstance ri = new RenderInstance();
            ri.Type = RenderInstanceType.LineList;
            ri.Vertices = verts;
            _renderQueue.AddRenderInstance(ri);
        }

        public override void DrawTransform(ref Transform xf)
        {
            float axisScale = 0.4f;
            Vector2 p1 = xf.Position;

            Vector2 p2 = p1 + axisScale * xf.R.col1;
            DrawSegment(p1, p2, Color.Red);

            p2 = p1 + axisScale * xf.R.col2;
            DrawSegment(p1, p2, Color.Green);
        }

        private VertexPositionColor[] _vertsLines = new VertexPositionColor[100000];
        private VertexPositionColor[] _vertsFill = new VertexPositionColor[100000];
        public static SpriteBatch _batch;
        public static SpriteFont _font;
        public static GraphicsDevice _device;
    }
}
